/** 导出 Excel */
import { saveAs } from 'file-saver';
import * as XLSX from 'xlsx';

/** 数据生成数组 */
const generateArray = (table: any) => {
	let out = [];
	let rows = table.querySelectorAll('tr');
	let ranges = [];
	for (let R = 0; R < rows.length; ++R) {
		let outRow = [];
		let row = rows[R];
		let columns = row.querySelectorAll('td');
		for (let C = 0; C < columns.length; ++C) {
			let cell = columns[C];
			let colspan = cell.getAttribute('colspan');
			let rowspan = cell.getAttribute('rowspan');
			let cellValue = cell.innerText;
			if (cellValue !== '' && cellValue == +cellValue) cellValue = +cellValue;

			//Skip ranges
			ranges.forEach(function (range) {
				if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
					for (let i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
				}
			});

			//Handle Row Span
			if (rowspan || colspan) {
				rowspan = rowspan || 1;
				colspan = colspan || 1;
				ranges.push({
					s: {
						r: R,
						c: outRow.length
					},
					e: {
						r: R + rowspan - 1,
						c: outRow.length + colspan - 1
					}
				});
			}

			//Handle Value
			outRow.push(cellValue !== '' ? cellValue : null);

			//Handle Colspan
			if (colspan) for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
		}
		out.push(outRow);
	}
	return [out, ranges];
};

/** 生成日期函数 */
const datenum = (v: Date) => {
	const epoch = Date.parse(v.toString());
	const day = 24 * 60 * 60 * 1000;
	const date = Date.UTC(1899, 11, 30);
	return (epoch - new Date(date).getTime()) / day;
};

const Workbook = (): { SheetNames: string[]; Sheets: any } => {
	return {
		SheetNames: [],
		Sheets: {}
	};
};

const sheetFromArrayOfArrays = (data: any) => {
	let ws = {};
	let range = {
		s: {
			c: 10000000,
			r: 10000000
		},
		e: {
			c: 0,
			r: 0
		}
	};
	for (let R = 0; R != data.length; ++R) {
		for (let C = 0; C != data[R].length; ++C) {
			if (range.s.r > R) range.s.r = R;
			if (range.s.c > C) range.s.c = C;
			if (range.e.r < R) range.e.r = R;
			if (range.e.c < C) range.e.c = C;
			let cell = {
				v: data[R][C],
				t: '',
				z: ''
			};
			if (cell.v == null) continue;
			let cell_ref = XLSX.utils.encode_cell({
				c: C,
				r: R
			});

			if (typeof cell.v === 'number') cell.t = 'n';
			else if (typeof cell.v === 'boolean') cell.t = 'b';
			else if (cell.v instanceof Date) {
				cell.t = 'n';
				cell.z = XLSX.SSF._table[14];
				cell.v = datenum(cell.v);
			} else cell.t = 's';

			ws[cell_ref] = cell;
		}
	}
	if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
	return ws;
};

const s2ab = (s: string) => {
	const buf = new ArrayBuffer(s.length);
	const view = new Uint8Array(buf);
	for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
	return buf;
};

/** 根据表格ID 导出数据 */
export const exportTableToExcel = (id: string) => {
	let theTable = document.getElementById(id);
	let oo = generateArray(theTable);
	let ranges = oo[1];

	/* original data */
	let data = oo[0];
	const ws_name = 'SheetJS';

	let wb = Workbook();
	let ws = sheetFromArrayOfArrays(data);

	/* add ranges to worksheet */
	// ws['!cols'] = ['apple', 'banan'];
	ws['!merges'] = ranges;

	/* add worksheet to workbook */
	wb.SheetNames.push(ws_name);
	wb.Sheets[ws_name] = ws;

	let wbout = XLSX.write(wb, {
		bookType: 'xlsx',
		bookSST: false,
		type: 'binary'
	});

	saveAs(
		new Blob([s2ab(wbout)], {
			type: 'application/octet-stream'
		}),
		`${datenum(new Date())}.xlsx`
	);
};

/** JSON 数据转表格 */
export const exportJsonToExcel = ({ multiHeader = [], header = [] as any, data = [] as string[], filename = '', merges = [], autoWidth = true, bookType = 'xlsx' } = {}) => {
	/* original data */
	filename = filename || 'excel-list';
	data = [...data];
	data.unshift(header);

	for (let i = multiHeader.length - 1; i > -1; i--) {
		data.unshift(multiHeader[i]);
	}

	let ws_name = new Date().getFullYear() + '年' + new Date().getMonth() + 1 + '月' + new Date().getDate() + '日';

	let wb = Workbook();
	let ws = sheetFromArrayOfArrays(data);

	if (merges.length > 0) {
		if (!ws['!merges']) ws['!merges'] = [];
		merges.forEach(item => {
			ws['!merges'].push(XLSX.utils.decode_range(item));
		});
	}

	if (autoWidth) {
		/*设置worksheet每列的最大宽度*/
		const colWidth = data.map((row: any) =>
			row.map((val: any) => {
				/*先判断是否为null/undefined*/
				if (val == null) {
					return {
						wch: 10
					};
				} else if (val.toString().charCodeAt(0) > 255) {
					/*再判断是否为中文*/
					return {
						wch: val.toString().length * 2
					};
				} else {
					return {
						wch: val.toString().length
					};
				}
			})
		);
		/*以第一行为初始值*/
		let result = colWidth[0];
		for (let i = 1; i < colWidth.length; i++) {
			for (let j = 0; j < colWidth[i].length; j++) {
				if (result[j]['wch'] < colWidth[i][j]['wch']) {
					result[j]['wch'] = colWidth[i][j]['wch'];
				}
			}
		}
		ws['!cols'] = result;
	}

	/* add worksheet to workbook */
	wb.SheetNames.push(ws_name);
	wb.Sheets[ws_name] = ws;

	let wbout = XLSX.write(wb, {
		bookType: bookType as XLSX.BookType,
		bookSST: false,
		type: 'binary'
	});
	saveAs(
		new Blob([s2ab(wbout)], {
			type: 'application/octet-stream'
		}),
		`${filename}.${bookType}`
	);
};

/** 表格 key 值转换 */
export const convertData = (rows: any, map: any) => {
	console.log(rows, map);

	map = map
		? map
		: {
				id: '编号',
				username: '姓名',
				password: '密码',
				isDisabled: '用户状态',
				isRobot: '是否机器人',
				org: '机构'
		  };

	/**
     *  header => ['id', '手机号', '用户名', ... ]
        data => [
	        ["604f764971f93f3ac8f365c2", "13800000002", "管理员",.... ]
	    ]
     */

	const enKeys = Object.keys(rows[0]);
	const header = enKeys.map(enKey => {
		return map[enKey];
	});
	const data = rows.map((obj: any) => {
		return Object.values(obj);
	});

	return { header, data };
};
